﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CoreUtils.WIL
{
    /// <summary>
    /// Filter functions from WIL library
    /// </summary>
    public class Filter
    {
        public enum Sobel : int
        {
            SobelDir = 0,
            SobelFilter = 1
        };

        public enum Average : int
        {
            AverageFilter = 0,
            AverageMxN = 1
        };

        public enum Median : int
        {
            MedianApproxFilter = 0,
            MedianFilter = 1,
            MedianMxN = 2
        };

        public enum Gauss : int
        {
            Gauss1D = 0,
            Gauss2D = 1,
            GaussFilter = 2
        };

        public enum AddNoise : int
        {
            Gauss = 0,
            SaltAndPepper = 1,
            Uniform = 2
        };

        #region Low Pass Filters
        public static FVIL.Data.CFviImage addNoiseGauss(FVIL.Data.CFviImage src,
            double ave, double var)
        {
            FVIL.Filter.CFviAddNoiseGauss parser = new FVIL.Filter.CFviAddNoiseGauss();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviAddNoiseGauss.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviAddNoiseGauss.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Ave = ave;
            parser.Var = var;
            parser.Seed = 0;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage addNoiseSaltAndPepper(FVIL.Data.CFviImage src,
            double pepVal, double pepRate, double saltVal, double saltRate)
        {
            FVIL.Filter.CFviAddNoiseSaltAndPepper parser = new FVIL.Filter.CFviAddNoiseSaltAndPepper();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviAddNoiseSaltAndPepper.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviAddNoiseSaltAndPepper.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.PepperVal = pepVal;
            parser.PepperRate = pepRate;
            parser.SaltVal = saltVal;
            parser.SaltRate = saltRate;
            parser.Seed = 0;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage addNoiseUniform(FVIL.Data.CFviImage src,
            double low, double high)
        {
            FVIL.Filter.CFviAddNoiseUniform parser = new FVIL.Filter.CFviAddNoiseUniform();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviAddNoiseUniform.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviAddNoiseUniform.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Low = low;
            parser.High = high;
            parser.Seed = 0;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage averageFilter(FVIL.Data.CFviImage src,
            int borderMode)
        {
            FVIL.Filter.CFviAverageFilter parser = new FVIL.Filter.CFviAverageFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviAverageFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviAverageFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage averageMxN(FVIL.Data.CFviImage src,
            int borderMode, int horz, int vert)
        {
            FVIL.Filter.CFviAverageMxN parser = new FVIL.Filter.CFviAverageMxN();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviAverageMxN.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviAverageMxN.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Horz = horz;
            parser.Vert = vert;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage doGFilter(FVIL.Data.CFviImage src, int procMode,
            double sigma1, double sigma2, int borderMode, int borderValue)
        {
            FVIL.Filter.CFviDoGFilter parser = new FVIL.Filter.CFviDoGFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviDoGFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviDoGFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ProcMode = FVIL.Filter.ProcMode.FIR;
            parser.Sigma1 = 0.6;
            parser.Sigma2 = 3.0;
            parser.BorderValue = 0;
            parser.BorderMode = FVIL.BorderMode.None;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage gaussian1DFilter(FVIL.Data.CFviImage src,
            int procMode, int borderMode, double borderValue, double sigma,
            int derivative, int directionMode)
        {
            FVIL.Filter.CFviGaussian1DFilter parser = new FVIL.Filter.CFviGaussian1DFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviGaussian1DFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviGaussian1DFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Derivative = derivative;
            parser.DerivativeDirection = (FVIL.Filter.DerivativeDirection)directionMode;
            parser.ProcMode = (FVIL.Filter.ProcMode)procMode;
            parser.Sigma = sigma;
            parser.BorderValue = borderValue;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage gaussian2DFilter(FVIL.Data.CFviImage src,
            int procMode, int borderMode, double borderValue, double sigma,
            int derivativeX, int derivativeY)
        {
            FVIL.Filter.CFviGaussian2DFilter parser = new FVIL.Filter.CFviGaussian2DFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviGaussian2DFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviGaussian2DFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.DerivativeX = derivativeX;
            parser.DerivativeY = derivativeY;
            parser.ProcMode = (FVIL.Filter.ProcMode)procMode;
            parser.Sigma = sigma;
            parser.BorderValue = borderMode;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage gaussianFilter(FVIL.Data.CFviImage src,
            int procMode, int borderMode, double borderValue, double sigma)
        {
            FVIL.Filter.CFviGaussianFilter parser = new FVIL.Filter.CFviGaussianFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviGaussianFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviGaussianFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ProcMode = (FVIL.Filter.ProcMode)procMode;
            parser.Sigma = sigma;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.BorderValue = borderValue;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage medianApproxFilter(FVIL.Data.CFviImage src,
            int borderMode)
        {
            FVIL.Filter.CFviMedianApproxFilter parser = new FVIL.Filter.CFviMedianApproxFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviMedianApproxFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviMedianApproxFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage medianFilter(FVIL.Data.CFviImage src,
            int borderMode)
        {
            FVIL.Filter.CFviMedianFilter parser = new FVIL.Filter.CFviMedianFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviMedianFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviMedianFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage medianMxN(FVIL.Data.CFviImage src,
            int horz, int vert)
        {
            FVIL.Filter.CFviMedianMxN parser = new FVIL.Filter.CFviMedianMxN();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviMedianMxN.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviMedianMxN.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Horz = horz;
            parser.Vert = vert;
            parser.BorderMode = FVIL.Filter.MedianMxNBorderMode.None;
            parser.Execute();
            return dst;
        }

        #endregion


        #region High Pass Filters
        public static FVIL.Data.CFviImage cannyEdge(FVIL.Data.CFviImage src)
        {
            FVIL.Filter.CFviCannyEdge parser = new FVIL.Filter.CFviCannyEdge();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviCannyEdge.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviCannyEdge.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ThresholdMode = FVIL.Filter.CannyEdgeThresholdMode.Ratio;
            parser.RatioThresholdL = 0.0;
            parser.RatioThresholdH = 0.0;
            parser.MagThresholdL = 13107;
            parser.MagThresholdH = 45874;
            parser.Sigma = 1.0;
            parser.MinLength = 1;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage kirsch(FVIL.Data.CFviImage src, int calcMode,
            double denom)
        {
            FVIL.Filter.CFviKirsch parser = new FVIL.Filter.CFviKirsch();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviKirsch.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviKirsch.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.CalcMode = (FVIL.Filter.KirschCalcMode)calcMode;
            parser.Denom = denom;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage laplacianFilter(FVIL.Data.CFviImage src,
            int matrixType, int borderMode)
        {
            FVIL.Filter.CFviLaplacianFilter parser = new FVIL.Filter.CFviLaplacianFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviLaplacianFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviLaplacianFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.MatrixType = (FVIL.Filter.MatrixType)matrixType;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage loGFilter(FVIL.Data.CFviImage src, int procMode,
            int borderMode, double sigma)
        {
            FVIL.Filter.CFviLoGFilter parser = new FVIL.Filter.CFviLoGFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviLoGFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviLoGFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ProcMode = (FVIL.Filter.ProcMode)procMode;
            parser.Sigma = sigma;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage prewitt(FVIL.Data.CFviImage src, int calcMode)
        {
            FVIL.Filter.CFviPrewitt parser = new FVIL.Filter.CFviPrewitt();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviPrewitt.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviPrewitt.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.CalcMode = (FVIL.Filter.PrewittCalcMode)calcMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage robertsFilter(FVIL.Data.CFviImage src, int borderMode)
        {
            FVIL.Filter.CFviRobertsFilter parser = new FVIL.Filter.CFviRobertsFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviRobertsFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviRobertsFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage sobelDir(FVIL.Data.CFviImage src, int borderMode)
        {
            FVIL.Filter.CFviSobelDir parser = new FVIL.Filter.CFviSobelDir();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviSobelDir.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviSobelDir.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.BorderValue = 0;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage sobelFilter(FVIL.Data.CFviImage src,
            int borderMode, int calcMode)
        {
            FVIL.Filter.CFviSobelFilter parser = new FVIL.Filter.CFviSobelFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviSobelFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviSobelFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.CalcMode = (FVIL.Filter.SobelCalcMode)calcMode;
            parser.BorderMode = (FVIL.BorderMode)borderMode;
            parser.Execute();
            return dst;
        }

        #endregion

        #region Other Filters
        public static FVIL.Data.CFviImage bFilter(FVIL.Data.CFviImage src, int colorMode,
            int directMode, int xdot, int ydot)
        {
            FVIL.Filter.CFviBFilter parser = new FVIL.Filter.CFviBFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviBFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviBFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.Color = (FVIL.Filter.BFilterColor)colorMode;
            parser.Xdot = xdot;
            parser.Ydot = ydot;
            parser.Direct = (FVIL.Filter.BFilterDirect)directMode;
            parser.Execute();
            return dst;
        }

        public static FVIL.Data.CFviImage stegerFilter(FVIL.Data.CFviImage src, int lineMode,
            double sigma, double threshold)
        {
            FVIL.Filter.CFviStegerFilter parser = new FVIL.Filter.CFviStegerFilter();
            FVIL.Data.CFviImage dst1 = new FVIL.Data.CFviImage();
            FVIL.Data.CFviImage dst2 = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviStegerFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviStegerFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst1;
            parser.DstImages[1] = dst2;
            if (!parser.IsValid())
                parser.Validate();
            parser.LineMode = (FVIL.Filter.LineMode)lineMode;
            parser.Sigma = sigma;
            parser.Threshold = threshold;
            parser.Execute();

            FVIL.Data.CFviImage tmp = new FVIL.Data.CFviImage();
            tmp.SetSize(dst1.HorzSize, dst1.VertSize, FVIL.ImageType.RGB32, 1);
            dst1.Depth = dst1.CalcDepth();
            dst1.SignedToRGB(0, tmp, 1);
            return tmp;
        }

        public static FVIL.Data.CFviImage thinningFilter(FVIL.Data.CFviImage src,
            int objColor, int thinningMode)
        {
            FVIL.Filter.CFviThinningFilter parser = new FVIL.Filter.CFviThinningFilter();
            FVIL.Data.CFviImage dst = new FVIL.Data.CFviImage();
            int valid = FVIL.Filter.CFviThinningFilter.CheckValidity(src);
            if (valid != FVIL.ErrorCode._SUCCESS)
                throw new FVIL.CFviException(valid, "FVIL.Filter.CFviThinningFilter.CheckValidity");
            parser.SrcImages[0] = src;
            parser.DstImages[0] = dst;
            if (!parser.IsValid())
                parser.Validate();
            parser.ObjectColor = (FVIL.Filter.ObjectColor)objColor;
            parser.ThinningMode = (FVIL.Filter.ThinningMode)thinningMode;
            parser.Execute();
            return dst;
        }

        #endregion
    }
}
